<?php
/**
 * Created by PhpStorm.
 * User: Inhere
 * Date: 2015/1/30
 * Use : ...
 * File: SimpleDatastorage.php
 */

namespace ulue\libs\datastorage;

use ulue\core\abstracts\AbstractCore;

class SimpleDatastorage extends AbstractCore implements /*\Serializable,*/ \ArrayAccess, \Countable, \IteratorAggregate
{
    /**
     * data storge
     * @var array
     */
    protected $data = [];

    public function __construct(array $data = [])
    {
        $this->data = $data;

        $this->init();
    }

    /**
     * 初始化信息
     */
    public function init()
    {}

    /**
     * getData
     * @return array
     */
    public function getData()
    {
        return $this->data;
    }

    /**
     * setData
     * @param array $data
     */
    public function setData(array $data)
    {
        $this->data = $data;

        return $this;
    }

    /**
     * exists
     * @param  string $name
     * @return mixed
     */
    public function exists($name)
    {
        return array_key_exists(trim($name), $this->data);
    }

    public function add($name, $value)
    {
        if ( $this->exists($name) ) {
            $this->data[$name] = $value;
        }

        return $this;
    }

    /**
     * @param string $name
     * @param string $value
     */
    public function __set($name, $value)
    {
        $setter = 'set' . ucfirst($name);

        if (method_exists($this, $setter)) {
            $this->$setter($value);
        } else if ( $this->exists($name) ) {
            $this->data[$name] = $value;
        }

        parent::__set($name, $value);
    }

    /**
     * @return string
     */
    public function __get($name)
    {
        $getter = 'get' . ucfirst($name);

        if ( method_exists($this, $getter) ) {

            return $this->$getter();
        } elseif ( $this->exists($name) ) {

            return  $this->data[$name];
        }

        return parent::__get($name);
    }

    /**
     * @param  string $name
     * @param  array $args
     * @return mixed
     */
    public function __call($name, $args)
    {
        $prefix = substr($name, 0, 3);
        $attr = lcfirst( substr($name, 4) );

        if ( in_array( $prefix, ['get', 'set']) && isset($this->data[$attr]) ) {

            if ( $prefix == 'get') {
                return $this->data[$attr];
            }

            if (isset($args[0])) {
                $this->data[$attr] = $args[0];

                return $this;
            }
        }

        return null;
    }

////////////////////////////////////////// array iterator ////////////////////////////////////////////

    /**
     * Defined by IteratorAggregate interface
     * Returns an iterator for this object, for use with foreach
     * @return \ArrayIterator
     */
    public function getIterator()
    {
        return new \ArrayIterator( $this->data );
    }

    /**
     * Checks whether an offset exists in the iterator.
     * @param   mixed  $offset  The array offset.
     * @return  boolean  True if the offset exists, false otherwise.
     */
    public function offsetExists($offset)
    {
        return $this->exists($offset);
    }

    /**
     * Gets an offset in the iterator.
     * @param   mixed  $offset  The array offset.
     * @return  mixed  The array value if it exists, null otherwise.
     */
    public function offsetGet($offset)
    {
        return $this->$offset;
    }

    /**
     * Sets an offset in the iterator.
     * @param   mixed  $offset  The array offset.
     * @param   mixed  $value   The array value.
     * @return  void
     */
    public function offsetSet($offset, $value)
    {
        $this->$offset = $value;
    }

    /**
     * Unset an offset in the iterator.
     * @param   mixed  $offset  The array offset.
     * @return  void
     */
    public function offsetUnset($offset)
    {
        if (isset($this->data[$offset])) {
            unset($this->data[$offset]);
        }
    }

    public function count()
    {
        return count($this->data);
    }

}// end class SimpleDatastorage